package mygame;

import com.jme3.input.KeyInput;
import com.jme3.animation.LoopMode;
import com.jme3.app.SimpleApplication;
import com.jme3.cinematic.Cinematic;
import com.jme3.cinematic.events.RotationTrack;
import com.jme3.collision.CollisionResults;
import com.jme3.export.binary.BinaryExporter;
import com.jme3.export.binary.BinaryImporter;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Ray;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.shadow.BasicShadowRenderer;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeCanvasContext;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import com.jme3.scene.shape.*;
import com.jme3.scene.*;

import java.io.*;

/**
 * you can embed a jme canvas inside a swing application
 * @author pgi
 */
public class SwingCanvasTest extends SimpleApplication {

    float lwh;
    float x;
    float y;
    float z;
    Geometry cube;
    int numOfShapes;
    String whichShape = "";
    boolean counter = false;
    PScreen newPS = new PScreen();
    Thread thread = new Thread();
    boolean isClicked = true;
Spatial newObject;
    public int SwingCanvasTest() {
        numOfShapes = 0;
        return numOfShapes;


    }
    //protected Geometry player2;
    //protected Geometry player3;
    Boolean isRunning = true;

    @Override
    public void simpleInitApp() {
        // activate windowed input behaviour
        flyCam.setDragToRotate(true);
        initKeys();

        // display a cube
        //We need to make a variable that counts the number of shapes that are being rendered
    /*if (numOfShapes == 1)
        {
        x = 0;
        y = 0;
        z = 0;
        }else if(numOfShapes >= 2)
        {
        //location will depend on how big the last shape was...
        }*/

        /*
        cube = makeSquare("Box1", 0, 0, 0, 1);
        Geometry cube2 = makeSquare("Box2", 1,1,1, 1);
        rootNode.attachChild(cube);
        rootNode.attachChild(cube2);
        
         */
        
        /*
        pyramid myNewPyramid = new pyramid(3f, 2f, 2f, 0f,0f,0f);
        Material mCyl = new Material(assetManager,
        "Common/MatDefs/Misc/ShowNormals.j3md");
        newObject = myNewPyramid.createPyramid();
        newObject.setMaterial(mCyl);
        rootNode.attachChild(newObject);
        */
        
        String newShapeMofo = "";
        if (isClicked == true) {
            try {
                BufferedReader in = new BufferedReader(new FileReader("shapeFile.txt"));
                newShapeMofo = in.readLine();

                in.close();
            } catch (IOException e) {
            }


            if (newShapeMofo.equals("square")) {
                /* triPrism myTriPrism = new triPrism(2f,1f,3f,0,0,0);
                Material mat = new Material(assetManager, 
                "Common/MatDefs/Misc/Unshaded.j3md");
                mat.setColor("Color",ColorRGBA.Blue);
                Spatial newObj = myTriPrism.createTriPrism();
                newObj.setMaterial(mat);
                rootNode.attachChild(newObj);
                
                triPrism myTriPrism1 = new triPrism(2f,1f,3f,0,0,0);
                Material mat1 = new Material(assetManager, 
                "Common/MatDefs/Misc/Unshaded.j3md");
                mat1.setColor("Color",ColorRGBA.Red);
                Geometry newObj1 = myTriPrism1.createEdges(.3f);
                newObj1.setMaterial(mat1);*/


                Geometry newObj1 = makeSquare("box");
                rootNode.attachChild(newObj1);
                rootNode.updateGeometricState();

                //Geometry newObj1 = makeSquare("box");
                // rootNode.attachChild(newObj1);
                //rootNode.updateGeometricState();

                System.out.println("textfile read square");
            } else if (counter
                    == false) {
                counter = true;
                System.out.println("didn't read square in text file");
            }
        } else {
            System.out.println("False");
        }
        /*
        sphere rotateSphere = new sphere(1f, -1f, -1f,1f);
        Material sMat = new Material(assetManager,
        "Common/MatDefs/Misc/Unshaded.j3md");
        sMat.setColor("Color",ColorRGBA.Green);
        Spatial sObject = rotateSphere.createEdges();
        sObject.setMaterial(sMat);
        rootNode.attachChild(sObject);
         */
        /*
        Cylinder testCyl = new Cylinder(100, 50, 3, 4,true);
        testCyl.setMode(Mesh.Mode.Lines);
        testCyl.setLineWidth(4f);
        Geometry newCyl = new Geometry("lineCyl", testCyl);
        
        Material mCyl = new Material(assetManager,
        "Common/MatDefs/Misc/ShowNormals.j3md");
        newCyl.setLocalTranslation(1.5f,1.5f,1.5f);
        newCyl.setMaterial(mCyl);
        rootNode.attachChild(newCyl);
         */
        //Light and Shadow
        DirectionalLight sun = new DirectionalLight();

        sun.setColor(ColorRGBA.White);

        sun.setDirection(
                new Vector3f(-1, -1, 1).normalizeLocal());
        rootNode.addLight(sun);
        BasicShadowRenderer bsr;

        rootNode.setShadowMode(ShadowMode.Off);
        bsr = new BasicShadowRenderer(assetManager, 256);

        bsr.setDirection(
                new Vector3f(-1, -1, -1).normalizeLocal());
        viewPort.addProcessor(bsr);

        rootNode.updateGeometricState();
    }

    public static void main(String[] args) {


        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;


                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(PScreen.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(PScreen.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(PScreen.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(PScreen.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                // create new JME appsettings
                AppSettings settings = new AppSettings(true);
                settings.setWidth(800);
                settings.setHeight(700);

                // create new canvas application
                SwingCanvasTest canvasApplication = new SwingCanvasTest();
                canvasApplication.setSettings(settings);
                canvasApplication.createCanvas(); // create canvas!
                JmeCanvasContext ctx = (JmeCanvasContext) canvasApplication.getContext();
                ctx.setSystemListener(canvasApplication);
                Dimension dim = new Dimension(1242, 531);
                ctx.getCanvas().setPreferredSize(dim);

                // Create Swing window
                PScreen window = new PScreen();
                window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                // Fill Swing window with canvas and swing components
                window.gamePanel.setLayout(new FlowLayout());// a panel
                window.gamePanel.add(ctx.getCanvas());                  // add JME canvas


                //whichShape = window.whatShapeToMake;

                // window.add(gamePanel);
                window.pack();

                // Display Swing window including JME canvas!
                window.setVisible(true);
                canvasApplication.startCanvas();
                canvasApplication.restart();

            }
        });
    }

    public static void setShape(String thisShape) {
        //whichShape = thisShape;
    }

    public Geometry makeSquare(String name) {
        Box box = new Box(new Vector3f(0, 0, 0), 1, 1, 1);
        Geometry square = new Geometry(name, box);
        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", ColorRGBA.randomColor());
        square.setMaterial(mat);
        return square;
    }

    //Swing Components
    public Geometry makeRect(String name, float x, float y, float z, float l, float w, float h) {
        Box box = new Box(new Vector3f(x, y, z), l, w, h);
        Geometry rectangle = new Geometry(name, box);
        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", ColorRGBA.randomColor());
        rectangle.setMaterial(mat);
        return rectangle;
    }

    //Saving a Node
    @Override
    public void destroy() {
        String userHome = System.getProperty("user.home");
        BinaryExporter exporter = BinaryExporter.getInstance();
        File file = new File(userHome + "/someFile.j3o");
        try {
            exporter.save(rootNode, file);


        } catch (IOException ex) {
            Logger.getLogger(SwingCanvasTest.class.getName()).log(Level.SEVERE, "Failed to save node!", ex);
        }
        super.destroy();
        System.out.println("Saved!!!!");
    }

    //Loading a Node
    public void loading() {
        String userHome = System.getProperty("user.home");
        BinaryImporter importer = BinaryImporter.getInstance();
        importer.setAssetManager(assetManager);
        File file = new File(userHome + "/someFile.j3o");
        try {
            Node loadedNode = (Node) importer.load(file);
            loadedNode.setName("loaded node");
            rootNode.attachChild(loadedNode);


        } catch (IOException ex) {
            Logger.getLogger(SwingCanvasTest.class.getName()).log(Level.SEVERE, "No saved node loaded!", ex);
        }
        System.out.println("Saved!!!!");


    }

    private void initKeys() {
        inputManager.setCursorVisible(true);
        inputManager.addMapping("select", new MouseButtonTrigger(mouseInput.BUTTON_LEFT));
        inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_J));
        inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_K));
        inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_U));
        inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_M));
        inputManager.addMapping("rotate45", new KeyTrigger(KeyInput.KEY_1));
        inputManager.addMapping("rotate90", new KeyTrigger(KeyInput.KEY_2));
        inputManager.addMapping("rotate180", new KeyTrigger(KeyInput.KEY_3));
        inputManager.addMapping("rotate270", new KeyTrigger(KeyInput.KEY_4));
        inputManager.addMapping("rotate360", new KeyTrigger(KeyInput.KEY_5));
        inputManager.addMapping("X", new KeyTrigger(KeyInput.KEY_X));
        inputManager.addMapping("Y", new KeyTrigger(KeyInput.KEY_Y));
        inputManager.addMapping("Z", new KeyTrigger(KeyInput.KEY_Z));
        inputManager.addMapping("Rotate", new KeyTrigger(KeyInput.KEY_SPACE));
        inputManager.addMapping("F1", new KeyTrigger(KeyInput.KEY_F1));//sphere
        inputManager.addMapping("F2", new KeyTrigger(KeyInput.KEY_F2));//cylinder
        inputManager.addMapping("F3", new KeyTrigger(KeyInput.KEY_F3)); //HEXPRISM
        inputManager.addMapping("F4", new KeyTrigger(KeyInput.KEY_F4)); //pyramid
        inputManager.addMapping("F5", new KeyTrigger(KeyInput.KEY_F5));//rectangular prism
        inputManager.addMapping("F6", new KeyTrigger(KeyInput.KEY_F6));//triprism
        inputManager.addMapping("F7", new KeyTrigger(KeyInput.KEY_F7));//cube
        inputManager.addMapping("F8", new KeyTrigger(KeyInput.KEY_F8));//pyramid cube base
        inputManager.addMapping("delete", new KeyTrigger(KeyInput.KEY_G));
       
        // Add the names to the action listener.
        inputManager.addListener(actionListener, new String[]{"Left", "Right", "Rotate", 
            "Up", "Down", "rotate45", "rotate90", "rotate180", "rotate270", "rotate360","delete",
            "X", "Y", "Z","F1","F2","F3","F4","F5","F6","F7","F8",});
        inputManager.addListener(analogListener, "select");
    }
    //The Selector Method
    
    private AnalogListener analogListener = new AnalogListener(){
        public void onAnalog(String name, float value, float tpf)
        {
            if (name.equals("select")) {
                //Reset results list
                CollisionResults results = new CollisionResults();
                //Convert screen click to 3d position
                Vector2f click2d = inputManager.getCursorPosition();
                Vector3f click3d = cam.getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 0f).clone();
                Vector3f dir = cam.getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 1f).subtractLocal(click3d);
                //Aim a ray from the click spot forwards
                Ray ray = new Ray(click3d, dir);
                //Collect intersections between ray and all nodes in results list
                rootNode.collideWith(ray, results);
                //Print so we know what is going on
                for (int i = 0; i < results.size(); i++) {
                    //for each hit we know the distance impact point and geometry
                    float dist = results.getCollision(i).getDistance();
                    Vector3f pt = results.getCollision(i).getContactPoint();
                    String target = results.getCollision(i).getGeometry().getName();
                    System.out.println("Selection #" + i + ":" + target + " at " + pt + ", " + dist + "WU away.");
                }
                //Use the results --we rotate the selected geom
                boolean selected = false;
                if (results.size() > 0) {
                    //The closest result is the target that the player picked
                    Geometry target =results.getClosestCollision().getGeometry();
                    target.rotate(0,value*speed,0);
                    target.getLocalTranslation();                  
                        
                    /*SpatialTrack track1 = new SpatialTrack(new float 1f, new Vector3f(0,0,0),new Quaternion(1,0,0, 0), new Vector3f(0,0,0));
                    Cinematic myCinema = new Cinematic(rootNode, 2);
                    cinematic addCinematicEvent(.5, track1);
                    stateManager.attach(myCinema);*/
                    
                    
                    // Quaternion rollme = new Quaternion();
                    //rollme
                    //here is the actions
                    

               }
            
            
        }
    }
    };
    
    private ActionListener actionListener = new ActionListener() {

        public void onAction(String name, boolean keyPressed, float tpf) {
            if (name.equals("Rotate") && keyPressed) {
                      /*Quaternion PITCH045 = new Quaternion().fromAngleAxis(FastMath.PI/4,   new Vector3f(1,0,0));
                        SpatialTrack rotation1 = new SpatialTrack(new float[] (3f,2f, 1f),new Vector3f[] (0,0,0),PITCH045, 3, );
                        //Node newNo = new Node();
                        //newNo.attachChild(newObject);
                       
                        Cinematic myCinema = new Cinematic(rootNode, 2);
                        myCinema.addCinematicEvent(0, rotation1);
                        stateManager.attach(myCinema);
                 * 
                 */
                
                
                        //target.rotate(0, value * speed, 0);
                        System.out.println("rotate biotch");
                    }
            if(name.equals("F1") && keyPressed)
            {
                sphere myBud = new sphere(2, -7,-3,0);
                Material sMat = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
                sMat.setColor("Color",ColorRGBA.Green);
                Spatial sObject = myBud.createSphere();
                sObject.setMaterial(sMat);
                rootNode.attachChild(sObject);
                
            }
            if(name.equals("F2") && keyPressed)
            {
                cylinder myCyl = new cylinder(.5f,2f,-7,0,0);
                Material sMat = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
                sMat.setColor("Color",ColorRGBA.Blue);
                Spatial sObject = myCyl.createCylinder();
                sObject.setMaterial(sMat);
                rootNode.attachChild(sObject);
                
            }
            if(name.equals("F3") && keyPressed)
            {
                hexPrism myHex = new hexPrism(1f,2f,1f,-4.5f,-2,0);
                Material sMat = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
                sMat.setColor("Color",ColorRGBA.Red);
                Spatial sObject = myHex.createHexPrism();
                sObject.setMaterial(sMat);
                rootNode.attachChild(sObject);
                
            }
            if(name.equals("F4")&&keyPressed)
            {
                pyramid myPyr = new pyramid(1f, 2f, 2f, -4.5f,1f,0f);
                Material mPyr = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
                mPyr.setColor("Color",ColorRGBA.Yellow);
                Spatial newPyr = myPyr.createPyramid();
                newPyr.setMaterial(mPyr);
                rootNode.attachChild(newPyr);
                
            }
            if(name.equals("F5") && keyPressed)
            {
                rectangularPrism myRect = new rectangularPrism(1,2,1,-1,-1,0);
                Material sMat = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
                sMat.setColor("Color",ColorRGBA.Green);
                Spatial sObject = myRect.createRectangularPrism();
                sObject.setMaterial(sMat);
                rootNode.attachChild(sObject);
                
            }
            if(name.equals("F6") && keyPressed)
            {
                triPrism myTri = new triPrism(1.5f,2f,2f,-1f,1f,0f);
                Material sMat = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
                sMat.setColor("Color",ColorRGBA.Orange);
                Spatial sObject = myTri.createTriPrism();
                sObject.setMaterial(sMat);
                rootNode.attachChild(sObject);
                
            }
            if(name.equals("F7") && keyPressed)
            {
                rectangularPrism myCube = new rectangularPrism(1,1,1,1,-1,0);
                Material sMat = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
                sMat.setColor("Color",ColorRGBA.Cyan);
                Spatial sObject = myCube.createRectangularPrism();
                sObject.setMaterial(sMat);
                rootNode.attachChild(sObject);
                
            }
            if(name.equals("F8") && keyPressed)
            {
                pyramid myPyrCube = new pyramid(2f, 2f, 2f, 1f,1f,0f);
                Material mPyr = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
                mPyr.setColor("Color",ColorRGBA.Pink);
                Spatial newPyr = myPyrCube.createPyramid();
                newPyr.setMaterial(mPyr);
                rootNode.attachChild(newPyr);
                
            }
            
            if(name.equals("delete") && keyPressed)
            {
                rootNode.detachAllChildren();
            }
            
        
        
                
                
                /*
                    if (name.equals("Right")) {
                        
                        Vector3f v = cube.getLocalTranslation();
                        cube.setLocalTranslation(v.x + 2 * speed, v.y, v.z);
                    }
                    if (name.equals("Left")) {
                        Vector3f v = cube.getLocalTranslation();
                        cube.setLocalTranslation(v.x - 2 * speed, v.y, v.z);
                    }
                    if ((name.equals("rotate45"))&&(name.equals("X"))) {
                        
                       // target.rotate(0, value * speed, 0);
                    }
                    if (name.equals("Up")) {
                       // Vector3f v = target.getLocalTranslation();
                        //target.setLocalTranslation(v.x + value * speed, v.y, v.z);
                    }
                    if (name.equals("Down")) {
                        //Vector3f v = target.getLocalTranslation();
                       // target.setLocalTranslation(v.x - value * speed, v.y, v.z);
                    }
                  
                 
                */
            

        }
    };

    public Quaternion rotateQuatX(int g) {
        Quaternion pitch = new Quaternion();
        pitch.fromAngleAxis(FastMath.PI * g / 120, new Vector3f(1, 0, 0));
        return pitch;
    }

    public Quaternion rotateQuatY(int g) {
        Quaternion yaw = new Quaternion();
        yaw.fromAngleAxis(FastMath.PI * g / 120, new Vector3f(0, 1, 0));
        return yaw;
    }

    public Quaternion rotateQuatZ(int g) {
        Quaternion roll = new Quaternion();
        roll.fromAngleAxis(FastMath.PI * g / 120, new Vector3f(0, 0, 1));
        return roll;
    }
}



